// CombatHelper.cs
//
// Copyright (c) 2007 Mike Strobel
//
// This source code is subject to the terms of the Microsoft Reciprocal License (Ms-RL).
// For details, see <http://www.opensource.org/licenses/ms-rl.html>.
//
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;

using Supremacy.Diplomacy;
using Supremacy.Entities;
using Supremacy.Game;
using Supremacy.Orbitals;
using Supremacy.Universe;

namespace Supremacy.Combat
{
    public static class CombatHelper
    {
        public static IList<CombatAssets> GetCombatAssets(MapLocation location)
        {
            var assets = new Dictionary<Civilization, CombatAssets>();
            var allFleets = new List<Fleet>();
            var results = new List<CombatAssets>();
            var sector = GameContext.Current.Universe.Map[location];

            //if (sector.Station != null)
            //{
            //    if (!assets.ContainsKey(sector.Station.Owner))
            //        assets[sector.Station.Owner] = new CombatAssets(sector.Station.Owner, location);
            //}

            allFleets.AddRange(GameContext.Current.Universe.FindAt<Fleet>(location));

            var engagingFleets = allFleets.Where(fleet => fleet.Order.WillEngageHostiles).ToList();

            engagingFleets.AddRange(
                from fleet in allFleets.Where(fleet => !fleet.Order.WillEngageHostiles)
                let fleetCopy = fleet
                where engagingFleets.Any(
                    otherFleet =>
                        WillEngage(fleetCopy.Owner, otherFleet.Owner) &&
                        Equals(fleetCopy.Sector.GetOwner(), otherFleet.Owner))
                select fleet);

            foreach (var fleet in engagingFleets)
            {
                var owner = fleet.Owner;

                if (!assets.ContainsKey(owner))
                    assets[owner] = new CombatAssets(owner, location);

                foreach (var ship in fleet.Ships)
                {
                    if (ship.IsCombatant)
                        assets[owner].CombatShips.Add(new CombatUnit(ship));
                    else
                        assets[owner].NonCombatShips.Add(new CombatUnit(ship));
                }
            }

            if (sector.Station != null)
            {
                var owner = sector.Station.Owner;

                if (!assets.ContainsKey(owner))
                    assets[owner] = new CombatAssets(owner, location);

                assets[owner].Station = new CombatUnit(sector.Station);
            }

            results.AddRange(assets.Values);

            //foreach (Orbital orbital in GameContext.Current.Universe.FindAt<Orbital>(location))
            //{
            //    Civilization owner = orbital.Owner;
            //    Ship ship = orbital as Ship;
            //    Station station = orbital as Station;
                
            //    if (owner == null)
            //        continue;
            //    if (!assets.ContainsKey(owner))
            //        assets[owner] = new CombatAssets(owner, location);
                
            //    if (ship != null)
            //    {
            //        if (ship.IsCombatant)
            //            assets[owner].CombatShips.Add(new CombatUnit(ship));
            //        else
            //            assets[owner].NonCombatShips.Add(new CombatUnit(ship));
            //    }
            //    else if (station != null)
            //    {
            //        assets[owner].Station = new CombatUnit(station);
            //    }
            //}

            //foreach (Civilization civA in assets.Keys)
            //{
            //    foreach (Civilization civB in assets.Keys)
            //    {
            //        if (civA == civB)
            //            continue;
            //        if (WillEngage(civA, civB))
            //        {
            //            if (!results.Contains(assets[civA]))
            //                results.Add(assets[civA]);
            //            if (!results.Contains(assets[civB]))
            //                results.Add(assets[civB]);
            //        }
            //    }    
            //}

            return results;
        }

        public static bool WillEngage(Civilization firstCiv, Civilization secondCiv)
        {
            if (firstCiv == null)
                throw new ArgumentNullException("firstCiv");
            if (secondCiv == null)
                throw new ArgumentNullException("secondCiv");
            if (firstCiv == secondCiv)
                return false;

            var relation = GameContext.Current.Relationships[firstCiv, secondCiv];
            if (relation == null)
                return false;

            switch (relation.Status)
            {
                case RelationshipStatus.Affiliated:
                case RelationshipStatus.Allied:
                case RelationshipStatus.Friendly:
                case RelationshipStatus.OtherIsMember:
                case RelationshipStatus.OwnerIsMember:
                case RelationshipStatus.OtherIsProtectorate:
                case RelationshipStatus.OwnerIsProtectorate:
                case RelationshipStatus.Peace:
                    return false;
                default:
                    return true;
            }
        }

        public static bool WillFightAlongside(Civilization firstCiv, Civilization secondCiv)
        {
            if (firstCiv == null)
                throw new ArgumentNullException("firstCiv");
            if (secondCiv == null)
                throw new ArgumentNullException("secondCiv");

            Relationship relation = GameContext.Current.Relationships[firstCiv, secondCiv];

            switch (relation.Status)
            {
                case RelationshipStatus.Affiliated:
                case RelationshipStatus.Allied:
                case RelationshipStatus.OtherIsMember:
                case RelationshipStatus.OwnerIsMember:
                case RelationshipStatus.OtherIsProtectorate:
                case RelationshipStatus.OwnerIsProtectorate:
                    return true;
                default:
                    return false;
            }
        }

        public static CombatOrders GenerateBlanketOrders(CombatAssets assets, CombatOrder order)
        {
            var owner = assets.Owner;
            var orders = new CombatOrders(owner, assets.CombatID);

            foreach (var ship in assets.CombatShips)
                orders.SetOrder(ship.Source, order);

            foreach (var ship in assets.NonCombatShips)
                orders.SetOrder(ship.Source, CombatOrder.Retreat);

            if (assets.Station != null &&
                assets.Station.Owner == owner)
            {
                orders.SetOrder(
                    assets.Station.Source,
                    (order == CombatOrder.Retreat) ? CombatOrder.Engage : order);
            }

            return orders;
        }
    }
}
